//
//

#import "AmapSearchTool.h"

#include "AppTool.h"

#import <AMapSearchKit/AMapSearchKit.h>

@interface AmapSearchTool () <AMapSearchDelegate>

@property(nonatomic, retain)  AMapSearchAPI *search;

@end

@implementation AmapSearchTool

-(instancetype)init
{
    self = [super init];
    if (self)
    {
        self.search = [[AMapSearchAPI alloc] init];
        self.search.delegate = self;
    }
    
    return self;
}

-(void)getGeocodeWithAddress:(NSString*)addr City:(NSString*)city
{
    AMapGeocodeSearchRequest *geo = [[AMapGeocodeSearchRequest alloc] init];
    geo.address = addr;
    geo.city = city;
    
    [self.search AMapGeocodeSearch:geo];
}

-(void)getRegeocodeWithLat:(double)lat Lng:(double)lng Radius:(NSInteger)radius
{
    AMapReGeocodeSearchRequest *regeo = [[AMapReGeocodeSearchRequest alloc] init];
    regeo.location = [AMapGeoPoint locationWithLatitude: lat longitude:lng];
    regeo.radius = radius;
    regeo.requireExtension            = YES;
    
    [self.search AMapReGoecodeSearch:regeo];
}

-(void)poiSearchWithKeyWord:(NSString*) keyword POIType:(NSString*)type City:(NSString*)city
{
    AMapPOIKeywordsSearchRequest *request = [[AMapPOIKeywordsSearchRequest alloc] init];
    request.keywords = keyword;
    request.city = city;
    request.cityLimit           = YES;
    request.requireExtension    = YES;
    
    [self.search AMapPOIKeywordsSearch:request];
}

-(void)poiSearchWithKeyWord:(NSString*) keyword POIType:(NSString*)type AroundLat:(double) lat AroundLng:(double) lng AroundRound:(int) round City:(NSString*)city
{
    AMapPOIAroundSearchRequest *request = [[AMapPOIAroundSearchRequest alloc] init];
    request.keywords = keyword;
    request.location = [AMapGeoPoint locationWithLatitude:lat longitude:lng];
    request.radius = round;
    request.requireExtension    = YES;
    
    [self.search AMapPOIAroundSearch:request];
}

#pragma mark - AMapSearchDelegate

- (void)AMapSearchRequest:(id)request didFailWithError:(NSError *)error
{
    std::vector<POISearchData> v_datas;
    int code = -1;
    
    if ([request isKindOfClass:AMapPOIKeywordsSearchRequest.class])
    {
        if (AppTool::getInstance()->getPoiSearchDelegate())
        {
            AppTool::getInstance()->getPoiSearchDelegate()->onPoiKeySearchEnd(code, v_datas);
        }
    }
    else if ([request isKindOfClass:AMapPOIAroundSearchRequest.class])
    {
        if (AppTool::getInstance()->getPoiSearchDelegate())
        {
            AppTool::getInstance()->getPoiSearchDelegate()->onPoiAroundSearch(code, v_datas);
        }
    }
}

/* POI 搜索回调. */
- (void)onPOISearchDone:(AMapPOISearchBaseRequest *)request response:(AMapPOISearchResponse *)response
{
    std::vector<POISearchData> v_datas;
    int code = 0;
    if (response != nil && response.pois != nil)
    {
        v_datas.reserve((int)response.pois.count);
        
        NSArray<AMapPOI *> *pois = response.pois;
        for (int i = 0; i < pois.count; ++i)
        {
            AMapPOI* poi = (AMapPOI*)[pois objectAtIndex:i];
        
            POISearchData poidata;
        
            poidata.lat = poi.location.latitude;
            poidata.lng = poi.location.longitude;
            poidata.province = [poi.province UTF8String];
            poidata.city = [poi.city UTF8String];
            poidata.district = [poi.district UTF8String];
            poidata.adcode = [poi.adcode UTF8String];
            poidata.info = [poi.name UTF8String];
    
            v_datas.push_back(poidata);
        }
        
        code = 0;
    }
    else
    {
        code = -1;
    }
    
    if ([request isKindOfClass:AMapPOIKeywordsSearchRequest.class])
    {
        if (AppTool::getInstance()->getPoiSearchDelegate())
        {
            AppTool::getInstance()->getPoiSearchDelegate()->onPoiKeySearchEnd(code, v_datas);
        }
    }
    else if ([request isKindOfClass:AMapPOIAroundSearchRequest.class])
    {
        if (AppTool::getInstance()->getPoiSearchDelegate())
        {
            AppTool::getInstance()->getPoiSearchDelegate()->onPoiAroundSearch(code, v_datas);
        }
    }
}

/**
 * @brief 地理编码查询回调函数
 * @param request  发起的请求，具体字段参考 AMapGeocodeSearchRequest 。
 * @param response 响应结果，具体字段参考 AMapGeocodeSearchResponse 。
 */
- (void)onGeocodeSearchDone:(AMapGeocodeSearchRequest *)request response:(AMapGeocodeSearchResponse *)response
{
    int code = 0;
    std::vector<GeocodeAddress> v_datas;
    if (response != nil && response.geocodes != nil)
    {
        v_datas.reserve((int)response.geocodes.count);
        for (id geodata in response.geocodes)
        {
            AMapGeocode *obj = (AMapGeocode *)geodata;
            
            GeocodeAddress address;
            address.lat = [[obj location] latitude];
            address.lng = [[obj location] longitude];
            address.formatAddr = [[obj formattedAddress] UTF8String];
            address.province = [[obj province] UTF8String];
            address.city = [[obj city] UTF8String];
            address.district = [[obj district] UTF8String];
            address.town = [[obj township] UTF8String];
            address.street = [[obj neighborhood] UTF8String];
            address.adcode = [[obj adcode] UTF8String];
            
            v_datas.push_back(address);
        }
    }
    else
    {
        code = -1;
    }
    
    if (AppTool::getInstance()->getGeocodeDelegate())
    {
        AppTool::getInstance()->getGeocodeDelegate()->onGetGeocodeAddress(code, v_datas);
    }
}

/* 逆地理编码回调. */
- (void)onReGeocodeSearchDone:(AMapReGeocodeSearchRequest *)request response:(AMapReGeocodeSearchResponse *)response
{
    int code = 0;
    RegeocodeInfo info;
    if (response != nil && response.regeocode != nil)
    {
        info.formatAddr = [[response.regeocode formattedAddress] UTF8String];
        
        AMapAddressComponent *addressComponent = [response.regeocode addressComponent];
        
        info.province = [[addressComponent province] UTF8String];
        info.city = [[addressComponent city] UTF8String];
        info.district = [[addressComponent district] UTF8String];
        info.town = [[addressComponent township] UTF8String];
        info.street = [[addressComponent neighborhood] UTF8String];
        info.adcode = [[addressComponent adcode] UTF8String];
        
        info.v_Pois.reserve((int)(response.regeocode.pois.count));
        for (id poiid in [response.regeocode pois])
        {
            AMapPOI* poi = (AMapPOI*)poiid;
            
            PoiInRegeocode poidata;
            poidata.lat = [[poi location] latitude];
            poidata.lng = [[poi location] longitude];
            poidata.info = [[poi name] UTF8String];
            
            info.v_Pois.push_back(poidata);
            
        }
    }
    else
    {
        code = -1;
    }
    
    if (AppTool::getInstance()->getGeocodeDelegate())
    {
        AppTool::getInstance()->getGeocodeDelegate()->onGetRegeocodeInfo(code, info);
    }
        
}

- (void)dealloc
{
    if (self.search != nil)
    {
        [self.search release];
        self.search = nil;
    }
    
    [super dealloc];
}

@end
